package com.mzlion.test.easyokhttp.server.controller;

import com.mzlion.core.binary.Base64;
import com.mzlion.core.http.IPUtils;
import com.mzlion.core.io.FileUtils;
import com.mzlion.core.io.FilenameUtils;
import com.mzlion.core.json.gson.JsonUtil;
import com.mzlion.core.lang.CollectionUtils;
import com.mzlion.core.lang.StringUtils;
import com.mzlion.easyokhttp.HttpClient;
import com.mzlion.easyokhttp.http.Header;
import com.mzlion.test.easyokhttp.server.dto.ApiResult;
import com.mzlion.test.easyokhttp.server.dto.FileData;
import com.mzlion.test.easyokhttp.server.dto.TaoBaoIpInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Created by mzlion on 2017/3/23.
 */
@RestController
public class ApiController {

    //log
    private final Logger logger = LoggerFactory.getLogger(ApiController.class);

    @Value("${custom.serverUrl}")
    private String serverUrl;

    /**
     * 接收IP信息分析请求
     *
     * @param ip      ip地址
     * @param request HTTP请求对象
     * @return 接口处理结果
     */
    @RequestMapping(value = "/ip-info", method = RequestMethod.GET)
    public ApiResult<Object> getIpInfo(String ip, HttpServletRequest request) {
        logger.info(" <=== 接收IP信息分析请求，请求参数->ip={}", ip);
        ApiResult<Object> apiResult = new ApiResult<>(-1);
        if (StringUtils.isEmpty(ip)) {
            ip = IPUtils.getClientIp(request);
            logger.info(" ===> 接口参数ip为空，自动获取客户端IP->{}", ip);
            if (StringUtils.isEmpty(ip)) {
                apiResult.setErrorMessage("自动获取客户端IP失败");
                logger.error(" ===> 接收IP信息分析请求处理完毕->{}", apiResult);
                return apiResult;
            }
        } else if (!IPUtils.matchesIpv4(ip)) {
            apiResult.setErrorMessage("IP格式不正确");
            logger.error(" ===> 接收IP信息分析请求处理完毕->{}", apiResult);
            return apiResult;
        }

        TaoBaoIpInfo taoBaoIpInfo = HttpClient
                .get("http://ip.taobao.com/service/getIpInfo.php")
                .queryString("ip", ip)
                .asBean(TaoBaoIpInfo.class);
        if (taoBaoIpInfo.getCode() == 1) {
            apiResult.setErrorMessage((String) taoBaoIpInfo.getData());
            logger.error(" ===> 接收IP信息分析请求处理完毕->{}", apiResult);
            return apiResult;
        }
        apiResult.setCode(0);
        apiResult.setData(taoBaoIpInfo.getData());
        apiResult.setErrorMessage("IP信息获取成功");
        logger.info(" ===> 接收IP信息分析请求处理完毕->{}", apiResult);
        return apiResult;
    }

    /**
     * 普通的表单提交
     *
     * @param request HTTP请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/post/simple", method = RequestMethod.POST)
    public ApiResult<Map<String, Object>> simplePost(HttpServletRequest request) {
        logger.info(" <=== 接收普通的表单提交请求");
        ApiResult<Map<String, Object>> apiResult = new ApiResult<>();

        CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getServletContext());
        if (resolver.isMultipart(request)) {
            apiResult.setCode(-1);
            apiResult.setErrorMessage("本接口不支持文件上传`");
            logger.error(" ===> 接收普通的表单提交请求处理完毕->{}", apiResult);
            return apiResult;
        }
        this.handleRequestParams(request, apiResult);

        this.handleRequestHeaders(request, apiResult);

        logger.info(" ===> 接收普通的表单提交请求处理完毕->{}", apiResult);
        return apiResult;
    }

    /**
     * 含文件的表单提交
     *
     * @param request HTTP请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/post/form", method = RequestMethod.POST)
    public ApiResult<Map<String, Object>> formPost(HttpServletRequest request) throws IOException {
        logger.info(" <=== 接收含文件的表单提交请求");
        ApiResult<Map<String, Object>> apiResult = new ApiResult<>();

        this.handleRequestParams(request, apiResult);

        CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getServletContext());
        if (resolver.isMultipart(request)) {
            String realPath = request.getServletContext().getRealPath("");
            File parentFile = new File(realPath + "/public/imgs");
            FileUtils.forceMakeDir(parentFile);
            MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;

            Map<String, List<FileData>> fileDataMap = new LinkedHashMap<>();
            for (Map.Entry<String, List<MultipartFile>> entry : mRequest.getMultiFileMap().entrySet()) {
                List<MultipartFile> valueList = entry.getValue();
                if (CollectionUtils.isNotEmpty(valueList)) {
                    List<FileData> fileDataList = new LinkedList<>();
                    for (MultipartFile multipartFile : valueList) {
                        FileData fileData = new FileData();
                        fileData.setOldFilename(multipartFile.getOriginalFilename());
                        fileData.setFileExt(FilenameUtils.getFileExt(fileData.getOldFilename()));
                        fileData.setNewFilename(System.nanoTime() + "." + fileData.getFileExt());
                        fileData.setFileSize((int) multipartFile.getSize());
                        fileData.setShowUrl(serverUrl + "/public/imgs/" + fileData.getNewFilename());
                        multipartFile.transferTo(new File(parentFile, fileData.getNewFilename()));
                        fileDataList.add(fileData);
                    }
                    fileDataMap.put(entry.getKey(), fileDataList);
                }
            }
            if (CollectionUtils.isNotEmpty(fileDataMap)) {
                apiResult.setFileData(fileDataMap);
            }
        }

        logger.info(" ===> 接收含文件的表单提交请求处理完毕->{}", apiResult);
        return apiResult;
    }

    @RequestMapping(value = "/post/body/raw", method = RequestMethod.POST, consumes = {"text/plain", "application/json"})
    public ApiResult<Object> rawBodyPost(@RequestBody(required = false) String content, HttpServletRequest request) {
        logger.info(" <=== 接收提交请求体(POST Text Body)请求，请求参数->content={}", content);
        ApiResult<Object> apiResult = new ApiResult<>();
        if (StringUtils.hasLength(content)) {
            String contentType = request.getHeader(Header.CONTENT_TYPE);
            System.out.println("contentType = " + contentType);
            if (contentType.equals("text/plain")) {
                apiResult.setData(content);
            } else {
                apiResult.setData(JsonUtil.fromJson(content, Map.class));
            }
        }

        logger.info(" ===> 接收请求体(POST Text Body)请求处理完毕->{}", apiResult);
        return apiResult;
    }

    @RequestMapping(value = "/post/body/binary", method = RequestMethod.POST)
    public ApiResult<String> binaryBodyPost(@RequestBody byte[] data) {
        logger.info(" <=== 接收提交请求体(POST Binary Body)请求");
        ApiResult<String> apiResult = new ApiResult<>();
        apiResult.setData(Base64.encode(data));

        logger.info(" ===> 接收请求体(POST Binary Body)请求处理完毕->{}", apiResult);
        return apiResult;
    }

    private void handleRequestParams(HttpServletRequest request, ApiResult<Map<String, Object>> apiResult) {
        Map<String, Object> data = new LinkedHashMap<>();
        for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
            String[] valueList = entry.getValue();
            if (valueList != null) {
                if (valueList.length == 1) {
                    data.put(entry.getKey(), valueList[0]);
                } else {
                    data.put(entry.getKey(), valueList);
                }
            }
        }
        apiResult.setData(data);
    }

    private void handleRequestHeaders(HttpServletRequest request, ApiResult<?> apiResult) {
        List<String> ignoreHeaderList = Arrays.asList(
                Header.USER_AGENT.toLowerCase(), Header.ACCEPT_LANGUAGE.toLowerCase(),
                Header.CONTENT_TYPE.toLowerCase(), Header.CONTENT_LENGTH.toLowerCase(),
                "host", Header.CONNECTION.toLowerCase(), Header.ACCEPT_ENCODING.toLowerCase());

        Enumeration<String> enumeration = request.getHeaderNames();
        Map<String, String> headers = new LinkedHashMap<>();
        while (enumeration.hasMoreElements()) {
            String headerKey = enumeration.nextElement();
            if (!ignoreHeaderList.contains(headerKey.toLowerCase()))
                headers.put(headerKey, request.getHeader(headerKey));
        }

        if (CollectionUtils.isNotEmpty(headers)) apiResult.setHeaders(headers);
    }


}
